import { CallHandler, ExecutionContext, Injectable, NestInterceptor, BadGatewayException } from '@nestjs/common';
import { of } from 'rxjs';
import Axios from "axios"
import { InjectModel } from 'nestjs-typegoose';
import { ModelType } from '@typegoose/typegoose/lib/types';
import { IP } from '@libs/db/models/ip.models';
import { Subcode } from '@libs/db/models/subcode.models';
import { ModeEnum, Qrcode, TypeEnum } from '@libs/db/models/qrcode.models';
import { renderFile } from 'ejs';
import { resolve } from 'path';

@Injectable()
export class DisturInterceptor implements NestInterceptor {
  constructor(
    @InjectModel(Qrcode) private qrcodeModel: ModelType<Qrcode>,
    @InjectModel(IP) private IPModel: ModelType<IP>,
    @InjectModel(Subcode) private SubcodeModel: ModelType<Subcode>,
  ) { }

  async intercept(context: ExecutionContext, next: CallHandler) {

    const req = context.switchToHttp().getRequest();
    const res = context.switchToHttp().getResponse();

    /* 查询活码信息 */
    const qrcode = await this.qrcodeModel.findOne({ shortid: req.params.shortid })
    if (!qrcode) throw new BadGatewayException("未知参数")
    /* 判断显示限制  */
    if (qrcode.displaylimit) {
      /* 查询ip信息 */
      const ipmodel = await this.IPModel.findOne({ ip: this.getip(req), qrcode: qrcode._id });
      /* 判断ip是否重复 */
      if (ipmodel) {
        console.log(qrcode.codename + '--ip重复访问:' + ipmodel.ip)
        /* 查询子码信息 */
        const SubcodeModel = await this.SubcodeModel.findOne({ _id: ipmodel.subcodeid, status: true })
        /* 修改ip次数 */
        this.IPModel.updateOne({ _id: ipmodel._id, subcodeid: ipmodel.subcodeid }, { $inc: { sum: 1 }, time: Math.floor(Date.now() / 1000) }).then()

        if (SubcodeModel) {

          let versions = this.versions(req.headers["user-agent"])
          let url: string = SubcodeModel.suburl
          if (versions.ios) {
            if (!versions.weixin) {
              if (qrcode.types == TypeEnum.QQ) {
                url = `mqqapi://card/show_pslcard?src_type=internal&version=1&uin=${SubcodeModel.originalname}&card_type=person&source=qrcode`
              } else {
                url = 'weixin://'
              }
            }
          } else {
            if (qrcode.types != TypeEnum.QQ) {
              url = 'weixin://'
            }
          }
          console.log(versions.ios);

          switch (qrcode.mode) {
            case ModeEnum.url:
              return res.redirect(url);
            case ModeEnum.json:
              return res.send({
                url,
                name: SubcodeModel.originalname,
                path: SubcodeModel.path,
                id: SubcodeModel._id,
                type: qrcode.types
              })
            case ModeEnum.view:
              const data = await renderFile(`${resolve()}/public/views/index.ejs`, {
                url,
                name: SubcodeModel.originalname,
                path: SubcodeModel.path,
                id: SubcodeModel._id,
                type: qrcode.types
              });
              res.writeHead(200, { 'Content-Type': 'text/html' });
              return res.end(data);
          }
        } else {
          console.log(qrcode.codename + '--二维码不在,删除ip,计数')
          this.IPModel.deleteMany({ ip: ipmodel.ip }).then()
          return next.handle()
        }

      } else {
        console.log(qrcode.codename + '--暂无ip,计数')
        return next.handle()
      }
    } else {
      return next.handle()
    }
  }

  versions(navigator) {
    const u = navigator.toLowerCase()
    return {
      ios: !!u.match(/\(i[^;]+;( u;)? cpu.+mac os x/), //ios终端
      android: u.indexOf('android') > -1 || u.indexOf('linux') > -1, //android终端或者uc浏览器
      weixin: u.match(/MicroMessenger/gi) == "micromessenger" || u.indexOf("qq") > -1
    };
  }

  public getip(req): string {
    try {
      return (req.headers['x-wq-realip'] ||
        req.headers['X-Real-IP'] ||
        req.headers['x-forwarded-for'] ||
        req.connection.remoteAddress ||
        req.socket.remoteAddress ||
        req.connection.socket.remoteAddress ||
        req.ip).match(/\d+.\d+.\d+.\d+/)[0]
    } catch (e) {
      return "未知IP";
    }
  }


  public async ipmap(ip) {
    const usercity = await Axios.get(`https://api.map.baidu.com/location/ip?ak=HQi0eHpVOLlRuIFlsTZNGlYvqLO56un3&coor=bd09ll&ip=${ip}`, { headers: { 'Host': "api.map.baidu.com" } })
    switch (usercity.data.status) {
      case 0:
        return usercity.data.content.address
      case 1:
        return "国外IP"
      default:
        return "未知IP"
    }
  }

}